/**
 * Bezier曲线类
 * @date 2024.9.10
 * @author wz
 */

import { _decorator, Component, Node, v3, Vec3 } from 'cc';
const { ccclass, property } = _decorator;

/**
 * Bezier曲线类，用于计算贝塞尔曲线上的点
 */
export class BezierCurve {
    /**
     * 控制点数组
     */
    private _controlPoints: Vec3[];

    /**
     * 构造函数
     * @param controlPoints 控制点数组
     */
    constructor(controlPoints: Vec3[]) {
        this._controlPoints = controlPoints;
    }

    /**
     * 计算贝塞尔曲线上指定参数t的位置
     * @param t 参数t，范围在[0, 1]之间
     * @returns 贝塞尔曲线上对应t的位置
     */
    public interpolate(t: number): Vec3 {
        const n = this._controlPoints.length - 1;
        let x = 0;
        let y = 0;

        for (let i = 0; i <= n; i++) {
            const b = this.bernstein(i, n, t);
            x += this._controlPoints[i].x * b;
            y += this._controlPoints[i].y * b;
        }

        return v3(x, y);
    }

    /**
     * 计算伯恩斯坦多项式的值
     * @param i 当前项的索引
     * @param n 控制点数量减一
     * @param t 参数t，范围在[0, 1]之间
     * @returns 伯恩斯坦多项式的值
     */
    private bernstein(i: number, n: number, t: number): number {
        const binomialCoefficient = this.binomial(n, i);
        const power_t_i = Math.pow(t, i);
        const power_1_t_n_i = Math.pow(1 - t, n - i);

        return binomialCoefficient * power_t_i * power_1_t_n_i;
    }

    /**
     * 计算组合数C(n, k)
     * @param n 总数
     * @param k 选取的数量
     * @returns 组合数C(n, k)
     */
    private binomial(n: number, k: number): number {
        let result = 1;
        for (let i = 1; i <= k; i++) {
            result *= (n - k + i) / i;
        }
        return result;
    }
}